#include "RouletteWheelSelectionStrategy.h"
#include "Chromosome.h"

RouletteWheelSelectionStrategy::RouletteWheelSelectionStrategy() : SelectionStrategy()
{
}

Chromosome* RouletteWheelSelectionStrategy::selectOne(const QList<Chromosome*>& chromosomeList)
{
    TRACE_FUNC_ENTRY
    if(distributionList.isEmpty())
        countDistribution(chromosomeList);

    //qDebug() << "distributionList.size(): " << distributionList.size();

    double randDistribution = static_cast<double>(qrand()) / static_cast<double>(RAND_MAX);

    //qDebug() << "randDistribution: " << randDistribution;

    QList<double>::iterator ind = qUpperBound(distributionList.begin(), distributionList.end(), randDistribution);

    int index = ind - distributionList.begin();

    //qDebug() << "randDistribution: " << randDistribution << "index: " << index << "distribution: " << distributionList.at(index);

    TRACE_FUNC_EXIT
    return chromosomeList.value(index);
}

void RouletteWheelSelectionStrategy::resetTempData()
{
    distributionList.clear();
}

void RouletteWheelSelectionStrategy::countDistribution(const QList<Chromosome*>& chromosomeList)
{
    TRACE_FUNC_ENTRY
    double totalGenerationFitness = 0;

    for(int i=0;i<chromosomeList.size();++i)
        totalGenerationFitness += chromosomeList.at(i)->getFitness();

    double distributionSum = 0;

    //double averageGenerationFitness = totalGenerationFitness/chromosomeList.size();
    //qDebug() << "totalGenerationFitness: " << totalGenerationFitness;
    //qDebug() << "averageGenerationFitness: " << averageGenerationFitness;

    for(int i=0;i<chromosomeList.size();++i)
    {
        double chromFit = chromosomeList[i]->getFitness();
        double chromosomeProbability = chromFit/totalGenerationFitness;
        double chromosomeDistribution = distributionSum + chromosomeProbability;
        distributionSum = chromosomeDistribution;
        distributionList.append(chromosomeDistribution);
       /* qDebug() << i << " fit: " << chromosomeList[i]->getFitness()
                << " chromProb: " << chromosomeProbability
                << "chromDistrib: " << QString::number(chromosomeDistribution, 'f', 10)
                << " expected: " << chromFit/averageGenerationFitness;*/
    }
    //qDebug() << distributionList;

    TRACE_FUNC_EXIT
}
